package GameEngine;

import AIEngine.AIPlayer;

import java.io.*;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;

import GameEngine.gui.*;
/**
 *  The main class of PentagoPP by S.C.A.P.F.
 *  This class provides different game modes as you will see above
 *  It also handles the whole text game play and starts the gui
 */
public class Pentagorun extends Observable implements Observer {

    /**
     * The main method of the whole game.<br>
     * You can choose witch user interface you want to run:
     * <ul>
     *  <li>Graphical user Interface, based on "Processing", please type "gui"</li>
     *  <li>Text mode for playing with console, please type "text"</li>
     * </ul>
     *
     * After you have chosen the mode of the interface you will be able to choose the game play mode.
     * The following modes are available for text interface:
     * <ul>
     *  <li>Player vs. Player</li>
     *  <li>Player vs. AI</li>
     *  <li>AI vs. AI</li>
     *  <li>Netplayer as host</li>
     *  <li>Netplayer as client</li>
     * </ul>
     *
     * The game will start in the mode you have chosen.
     * @param args not able at this time
     */
	
	private Board tBoard;
	private Time timeBlack;
    private Time timeRed;
    private int leftTurns;
	
    public Pentagorun(){
    	
    } 
    
    public void startGame(int mode){
    	
        Player red = null;
        Player black = null;

        // initialize chosen mode
        switch (mode) {
        
            case 1:
                
                black = new StdPlayer(true); 
                red = new StdPlayer(false);  
                play(black, red);
                break;
                
            case 2:
                System.out.println("You have choosen Player vs. AI");              

                Random switcher = new Random();
                if ((switcher.nextInt(10) % 2) == 0) { // random mode for player colors
                    black = new StdPlayer(true);
                    red = new AIPlayer(false);
                    System.out.println("You are the black player!");
                } else {
                    black = new AIPlayer(true);
                    red = new StdPlayer(false);
                    System.out.println("You are the red player!");
                }
                
                play(black, red);
                break;
                
            case 3:
                black = new AIPlayer(true);
                red = new AIPlayer(false);
                play(black, red);
                break;
           
        }
    }
    


    /**
     * This method executes the game play of player 1 (black) and player 2 (red)
     * A while loop will run until status changes from 0 (OK) to:
     * <ul>
     *  <li> 1 - black wins</li>
     *  <li> 2 - red wins</li>
     *  <li> 3 - draw</li>
     *  <li>99 - error</li>
     * </ul>
     *
     * @param p1 Black Player
     * @param p2 Red Player
     */
    private void play(Player p1, Player p2) {

        // Both players get 10minutes for this play
        timeBlack = new Time(300.0);
        timeRed = new Time(300.0);

        // tBoard is the Board object in this class
        tBoard = new Board();

        // lets get us a empty Move
        Move move = null;
        
        // fin is false while its one players turn
        boolean fin = false;

        // loop while playing
        while (tBoard.getStatus().value() == 0) {
        	
        	/* Get leftTurns */
        	leftTurns = tBoard.getTurns();

        	// request black move
            if (tBoard.getPlayer()) {
                while (!fin) {

                    timeBlack.start(); // starts time counting

                    try {
                        System.out.println("Black (@) moves: ");
                        fin = true;
                        move = p1.request(move, leftTurns);
                        if (move == null) {
                            tBoard.getStatus().value(2);
                        } else {
                            tBoard.isValid(move.column(), move.row());
                            p2.confirm(tBoard.getStatus());

                            if (tBoard.getStatus().value() == 4) {
                                throw new Exception("Invalid move!");
                            }
                            tBoard.setMarble(move.column(), move.row(), move.black());
                            tBoard.rotate(move.element(), move.clockwise());
                        }
                    } catch (Exception e) {
                        fin = false;
                        notifyObservers(); // mossa non valida
                        System.out.println(e.getMessage());
                    }
                    timeBlack.end(); // stops time counting
                    System.out.println("Black time balance: " + timeBlack.getVolume() + "sec.");
                }
                notifyObservers();  // turno giocatore 1 finito REPAINT GUI
                // reset fin
                fin = false;
            } else { // request red move
                while (!fin) {

                    timeRed.start(); //start time counting

                    try {
                        System.out.println("Red (#) moves: ");
                        fin = true;
                        move = p2.request(move, leftTurns);
                        if (move == null) {
                            tBoard.getStatus().value(1);
                        } else {
                            tBoard.isValid(move.column(), move.row());
                            p1.confirm(tBoard.getStatus());
                            if (tBoard.getStatus().value() == 4) {
                                throw new Exception("Invalid move!");
                            }
                            tBoard.setMarble(move.column(), move.row(), move.black());
                            tBoard.rotate(move.element(), move.clockwise());
                        }
                    } catch (Exception e) {
                        fin = false;
                        notifyObservers(); // mossa non valida
                        System.out.println(e.getMessage());
                    }

                    timeRed.end(); // stops time counting
                    System.out.println("Red time balance: " + timeRed.getVolume() + "sec.");
                    notifyObservers(); //turno giocatore 2 finito REPAINT GUI

                }
            }
            
            /* Print game status (statistics) */
            System.out.println(tBoard);
            fin = false;
            tBoard.checkWin(tBoard.getPlayer()); //checks if opposite may becomes winner
            if (tBoard.getStatus().value() == 0) {
                tBoard.checkWin(!tBoard.getPlayer()); //checks if the actual player may becomes winner and overwrites status of the board
            }
        }

        notifyObservers(); // partita terminata REPAINT GUI
    }
    
    public int getGameStatus(){
    	return tBoard.getStatus().value();
    }

	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		
	}
}
